﻿using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;

namespace SplashScreen.Views
{
    public partial class Splash : Form
    {
        #region FullScreenFlags enum

        [Flags]
        public enum FullScreenFlags
        {
            SwHide = 0,
            ShowTaskbar = 0x1,
            HideTaskbar = 0x2,
            ShowSipButton = 0x4,
            HideSipButton = 0x8,
            SwRestore = 9,
            ShowStartIcon = 0x10,
            HideStartIcon = 0x20
        }

        #endregion

        #region Fields

        private static Splash splashScreen;

        #endregion

        #region Constructors

        public Splash()
        {
            InitializeComponent();
        }

        #endregion

        #region public

        public static void CloseSplashScreen()
        {
            if (splashScreen != null)
            {
                ThreadPool.QueueUserWorkItem(CloseOnOwnThread);
            }
        }

        private static void CloseOnOwnThread(object state)
        {
            Thread.Sleep(100);
            var del = new CallOnUIThread(splashScreen.Close);
            splashScreen.Invoke(del);
            splashScreen = null;
        }

        public static void ShowSplashScreen()
        {
            if (splashScreen == null)
            {
                ThreadPool.QueueUserWorkItem(ShowForm);
                while (splashScreen == null)
                {
                    Thread.Sleep(100);
                }
            }
        }

        protected override void OnActivated(EventArgs e)
        {
            base.OnActivated(e);
            SHFullScreen(Handle, (int) FullScreenFlags.HideTaskbar);
        }

        public static void UpdateSplashScreenText(string text)
        {
            if (splashScreen != null)
            {
                var del = new CallOnUIThreadWithMessage(splashScreen.UpdateText);
                splashScreen.Invoke(del, new[] {text});
            }
        }

        #endregion

        #region private

        [DllImport("aygshell.dll", SetLastError = true)]
        private static extern bool SHFullScreen(IntPtr hwnd, int state);

        private static void ShowForm(object state)
        {
            splashScreen = new Splash();
            Application.Run(splashScreen);
        }

        private void UpdateText(string text)
        {
            splashScreen.statusLabel.Text = text;
        }

        #endregion

        #region Nested type: CallOnUIThread

        private delegate void CallOnUIThread();

        #endregion

        #region Nested type: CallOnUIThreadWithMessage

        private delegate void CallOnUIThreadWithMessage(string message);

        #endregion
    }
}